package com.hwpt.interceptor;

import com.hwpt.constant.JwtClaimsConstant;
import com.hwpt.properties.JwtProperties;
import com.hwpt.utils.JwtUtil;
import io.jsonwebtoken.Claims;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * jwt令牌校验的拦截器
 */
@Component
@Slf4j
@RequiredArgsConstructor
public class JwtTokenUserInterceptor implements HandlerInterceptor {

    private final JwtProperties jwtProperties;
    
    private static final String BEARER_PREFIX = "Bearer ";

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 判断当前拦截到的是Controller的方法还是其他资源
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }

        // 处理OPTIONS预检请求 - 直接放行
        if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
            log.info("放行OPTIONS预检请求: {}", request.getRequestURI());
            return true;
        }

        //1、从请求头中获取令牌 - 优先尝试小写，因为很多客户端发送小写header
        String token = request.getHeader("authorization");
        log.info("小写authorization头: {}", token);
        
        // 如果小写为空，再尝试大写（标准格式）
        if (token == null) {
            token = request.getHeader("Authorization");
            log.info("大写Authorization头: {}", token);
        }
        
        // 如果配置了自定义header名称，也尝试
        if (token == null && jwtProperties.getUserTokenName() != null) {
            token = request.getHeader(jwtProperties.getUserTokenName());
            log.info("配置的token头[{}]: {}", jwtProperties.getUserTokenName(), token);
        }

        if (token == null || token.trim().isEmpty()) {
            log.info("JWT令牌为空，请求URI: {}", request.getRequestURI());
            response.setStatus(401);
            response.setContentType("application/json;charset=UTF-8");
            response.getWriter().write("{\"code\": 401, \"message\": \"未提供认证令牌\"}");
            return false;
        }

        // 处理Bearer前缀
        if (token.startsWith(BEARER_PREFIX)) {
            token = token.substring(BEARER_PREFIX.length()).trim();
            log.info("去除Bearer前缀后的token: {}", token);
        }

        //2、校验令牌
        try {
            log.info("开始JWT校验");
            Claims claims = JwtUtil.parseJWT(jwtProperties.getUserSecretKey(), token);

            // 获取用户ID - 根据实际类型处理
            Object userIdObj = claims.get(JwtClaimsConstant.USER_ID);
            String userId;

            if (userIdObj instanceof Long) {
                userId = String.valueOf(userIdObj);
            } else if (userIdObj instanceof Integer) {
                userId = String.valueOf(userIdObj);
            } else if (userIdObj != null) {
                userId = userIdObj.toString(); // 直接转为字符串
            } else {
                userId = null; // 或者设置默认值，如 "0"
            }
            
            log.info("解析出的用户ID: {}", userId);
            
            // 将用户ID存储到请求属性中，方便后续使用
            request.setAttribute(JwtClaimsConstant.USER_ID, userId);
            log.info("JWT校验成功，用户ID: {}", userId);
            
            //3、通过，放行
            return true;
        } catch (Exception ex) {
            log.error("JWT校验失败: {}", ex.getMessage(), ex);
            //4、不通过，响应401状态码
            response.setStatus(401);
            response.setContentType("application/json;charset=UTF-8");
            response.getWriter().write("{\"code\": 401, \"message\": \"认证失败: " + ex.getMessage() + "\"}");
            return false;
        }
    }
}